home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-06-17 | 47.8 KB | 1,597 lines | [TEXT/ALFA] |
- #===============================================================================
- #
- # htmlEngine.tcl (called from html.tcl)
- #
- # Part of HTML mode 1.4.1
- #
- # General Support Routines
- #
- # Copyright 1996, 1997 by Johan Linde <jl@theophys.kth.se>.
- # This software may be used freely, and distributed freely, as long as
- # the receiver is not obligated in any way by receiving it.
- #
- # If you make improvements to this file, please share them!
- #
- #===============================================================================
-
-
- proc htmlIsUnsignedInteger {str1} {
- return [regexp {^[0-9]+$} [string trim $str1]]
- }
-
- proc htmlIsPositiveInteger {str1} {
- return [expr ([htmlIsUnsignedInteger $str1] && ![regexp {^0+$} [string trim $str1]])]
- }
-
- proc htmlIsInteger {str} {
- return [regexp {^-?[0-9]+$} [string trim $str]]
- }
-
- # Checks to see if the current window is empty, except for whitespace.
- proc htmlIsEmptyFile {} {
- return [htmlIsWhite [getText 0 [maxPos]]]
- }
-
- # Quoting of strings for meta tags.
- proc htmlQuote {str} {
- regsub -all "#" $str {#;} str
- regsub -all "\"" $str {#qt;} str
- regsub -all "<" $str {#lt;} str
- regsub -all ">" $str {#gt;} str
- return $str
- }
-
- proc htmlUnQuote {str} {
- regsub -all {#qt;} $str "\"" str
- regsub -all {#lt;} $str "<" str
- regsub -all {#gt;} $str ">" str
- regsub -all {#;} $str "#" str
- return $str
- }
-
- proc htmlCommentStrings {} {
- if {![catch {search -f 0 -r 1 -i 1 -m 0 {<SCRIPT([ \t\r]+[^>]*>|>)} [getPos]} res1] &&
- ([catch {search -f 0 -r 1 -i 1 -m 0 {</SCRIPT>} [getPos]} res2] ||
- [lindex $res1 0] > [lindex $res2 0])} {
- return [list "/* " " */"]
- } else {
- return [list "<!-- " " -->"]
- }
- }
-
- # Create a string for URL mapping in Big Brother.
- proc htmlURLmap {} {
- global HTMLmodeVars
- set urlmap {}
- foreach hp $HTMLmodeVars(homePages) {
- set fld "[htmlURLescape [lindex $hp 0] 1]/"
- regsub -all ":" $fld "/" fld
- set url [htmlURLescape "[lindex $hp 1][lindex $hp 2]"]
- lappend urlmap "Msta:“$url”, Mend:“file:///$fld”"
- append urlmap ","
- }
- set urlmap [string trimright $urlmap ","]
- return $urlmap
- }
-
- # Escapes certain characters in URLs.
- proc htmlURLescape {str {slash 0}} {
- set hexa {0 1 2 3 4 5 6 7 8 9 A B C D E F}
- set nstr ""
- set exp "\[\001- \177-ˇ%<>\"#\?=&;|\\{\\}\\`^"
- if {$slash} {append exp "/"}
- append exp "\]"
- while {[regexp -indices $exp $str c]} {
- set asc [htmlAscii [string index $str [lindex $c 0]]]
- append nstr [string range $str 0 [expr [lindex $c 0] - 1]]
- append nstr % [lindex $hexa [expr $asc / 16]] [lindex $hexa [expr $asc % 16]]
- set str [string range $str [expr [lindex $c 1] + 1] end]
- }
- return "$nstr$str"
- }
-
- proc htmlURLescape2 {str} {
- set url ""
- regexp {[^#]*} $str url
- set anchor [string range $str [string length $url] end]
- return "[htmlURLescape $url]$anchor"
- }
-
- # Translate escaped characters in URLs.
- proc htmlURLunEscape {str} {
- set hexa {0 1 2 3 4 5 6 7 8 9 A B C D E F}
- set nstr ""
- while {[regexp -indices {%[0-9A-F][0-9A-F]} $str hex]} {
- append nstr [string range $str 0 [expr [lindex $hex 0] - 1]]
- append nstr [htmlAscii [expr 16 * [lsearch $hexa [string index $str [expr [lindex $hex 0] + 1]]] \
- + [lsearch $hexa [string index $str [expr [lindex $hex 0] + 2]]]] 1]
- set str [string range $str [expr [lindex $hex 1] + 1] end]
- }
- return "$nstr$str"
- }
-
- # Makes a line for browser error window.
- proc htmlBrwsErr {fil l lnum ln text path} {
- return "$fil[format "%$l\s" ""]; Line $lnum:[format "%$ln\s" ""]$text\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$path\r"
- }
-
-
- proc htmlIsTextFile {fil cmd} {
- getFileInfo $fil filetest
- if {$filetest(type) != "TEXT"} {
- $cmd "[file tail $fil] is not a text file."
- return 0
- }
- return 1
- }
-
- proc htmlAllSaved {msg} {
- set dirty 0
- foreach w [winNames] {
- getWinInfo -w $w arr
- if {$arr(dirty)} {set dirty 1; break}
- }
- if {$dirty} {
- set yn [eval [concat askyesno $msg]]
- if {$yn == "yes"} {saveAll}
- return $yn
- }
- return yes
- }
-
- proc htmlIsThereAHomePage {} {
- global HTMLmodeVars
- if {![llength $HTMLmodeVars(homePages)]} {
- alertnote "You must set a home page folder."
- htmlHomePages
- }
- return [llength $HTMLmodeVars(homePages)]
- }
-
- proc htmlWhichHomePage {msg} {
- global HTMLmodeVars
- foreach hp $HTMLmodeVars(homePages) {
- lappend hplist "[lindex $hp 1][lindex $hp 2]"
- }
- if {[catch {listpick -p "Select home page to $msg." $hplist} hp] || ![string length $hp]} {error ""}
- set home [lindex $HTMLmodeVars(homePages) [lsearch -exact $hplist $hp]]
- if {![file exists [lindex $home 0]] || ![file isdirectory [lindex $home 0]]} {
- alertnote "Can't find the folder for [lindex $home 1][lindex $home 2]"
- error ""
- }
- return $home
- }
-
- # Checks if a folder contains a home page folder or an include folder as a subfolder.
- proc htmlContainHpFolder {folder} {
- global HTMLmodeVars
- foreach p $HTMLmodeVars(homePages) {
- foreach i {0 4} {
- if {[llength $p] == $i} {continue}
- if {[string match "$folder:*" "[lindex $p $i]:"] && "[lindex $p $i]:" != "$folder:"} {
- return 1
- }
- }
- }
- return 0
- }
-
- # Asks for a folder and checks that it is not an alias.
- proc htmlGetDir {prompt} {
- while {1} {
- if {[file isdirectory [set folder [get_directory -p $prompt]]]} {
- break
- } else {
- alertnote "Sorry! Cannot resolve aliases."
- }
- }
- return [string trimright $folder :]
- }
-
- proc htmlAscii {char {num 0}} {
- if {$char == ""} {return 0}
- set str "\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
- append str "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
- append str " !\"#\$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- append str "\[\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177ÄÅÇÉÑÖÜáàâäãåçéèêë"
- append str "íìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈Δ«»… ÀÃÕŒœ–—"
- append str "“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ"
- if {$num} {
- return [string index $str [expr $char - 1]]
- } else {
- return [expr 1 + [string first $char $str]]
- }
- }
-
- proc htmlNotYet {} {
- alertnote "Not yet, but coming soon."
- }
-
- proc htmlDisabled {} {
- alertnote "Disabled function!"
- error "Disabled function!"
- }
-
- proc htmlSetCase {elem} {
- global HTMLmodeVars
- if {$HTMLmodeVars(useLowerCase)} {
- return [string tolower $elem]
- } else {
- return [string toupper $elem]
- }
- }
-
-
- # Returns a list of all attributes used in any HTML element.
- proc htmlGetAllAttrs {} {
- global htmlElemAttrOptional1 htmlElemAttrRequired1 htmlElemEventHandler1
-
- foreach elem [array names htmlElemAttrOptional1] {
- if {[info exists htmlElemAttrRequired1($elem)]} {
- append allHTMLattrs " " $htmlElemAttrRequired1($elem)
- }
- append allHTMLattrs " " $htmlElemAttrOptional1($elem)
- if {[info exists htmlElemEventHandler1($elem)]} {
- append allHTMLattrs " " [string toupper $htmlElemEventHandler1($elem)]
- }
- }
- return $allHTMLattrs
- }
-
-
- # Snatch the current selection into htmlCurSel, set flag whether there is one
- proc htmlGetSel {} {
- global htmlCurSel htmlIsSel
- set htmlCurSel [string trim [getSelect]]
- set htmlIsSel [string length $htmlCurSel]
- }
-
- #===============================================================================
- # File routines
- #===============================================================================
-
-
- # Determines width and height of a GIF file.
- proc htmlGIFWidthHeight {fil} {
- if {[catch {open $fil r} fid]} {return}
- seek $fid 6 start
- set width [expr [htmlReadOne $fid] + 256 * [htmlAscii [read $fid 1]]]
- set height [expr [htmlReadOne $fid] + 256 * [htmlAscii [read $fid 1]]]
- close $fid
- return [list $width $height]
- }
-
- # Extracts width and height of a jpeg file.
- # Algorithm from the perl script 'wwwimagesize' by
- # Alex Knowles, alex@ed.ac.uk
- # Andrew Tong, werdna@ugcs.caltech.edu
- proc htmlJPEGWidthHeight {fil} {
- if {[catch {open $fil r} fid]} {return}
- if {[htmlAscii [read $fid 1]] != 255 || [htmlAscii [read $fid 1]] != 216} {return}
- set ch ""
- while {![eof $fid]} {
- while {[htmlAscii $ch] != 255 && ![eof $fid]} {set ch [read $fid 1]}
- while {[htmlAscii $ch] == 255 && ![eof $fid]} {set ch [read $fid 1]}
- if {[set asc [htmlAscii $ch]] >= 192 && $asc <= 195} {
- seek $fid 3 current
- set height [expr 256 * [htmlAscii [read $fid 1]] + [htmlReadOne $fid]]
- set width [expr 256 * [htmlAscii [read $fid 1]] + [htmlReadOne $fid]]
- close $fid
- return [list $width $height]
- } else {
- set ln [expr 256 * [htmlAscii [read $fid 1]] + [htmlAscii [read $fid 1]] - 2]
- if {$ln < 0} {break}
- seek $fid $ln current
- }
- }
- close $fid
- }
-
- # Reads one character from an image file.
- # For some mysterious reason 10 and 13 has to be swapped.
- proc htmlReadOne {fid} {
- set c [htmlAscii [read $fid 1]]
- if {$c == 13} {
- set c 10
- } elseif {$c == 10} {
- set c 13
- }
- return $c
- }
-
-
- # Returns the URL to the current window.
- # Called with 0 if called from htmlGetFile.
- # Called with 1 if called from HTMLDblClick. (0 or 1 determines the error message.)
- proc htmlThisFilePath {errorMsg} {
- global HTMLmodeVars
-
- set thisFile [stripNameCount [lindex [winNames -f] 0]]
-
- # Look for BASE element.
- if {![catch {search -s -f 1 -r 1 -i 1 -m 0 {<BASE[ \t\r]+[^>]*>} 0} res] && \
- [regexp -nocase {HREF=\"?([^ \t\r\">]+)} [getText [lindex $res 0] \
- [lindex $res 1]] dum href]} {
- if {[catch {htmlBASEpieces $href} basestr]} {
- alertnote "Window contains invalid BASE element. Ignored."
- } else {
- return $basestr
- }
- }
-
- # Check if window is saved.
- if {![file exists $thisFile]} {
- if {$errorMsg} {
- set etxt "You must save the window, otherwise it cannot be determined\
- where the link is pointing."
- } else {
- set etxt "You must save the window. If you save, you will then be prompted\
- for a file to link to."
- }
- if {[lindex [dialog -w 400 -h 100 -t $etxt 10 10 390 60 \
- -b Save 20 70 85 90 \
- -b Cancel 110 70 175 90] 1]} {
- return
- }
-
- if {![catch {saveAs "Untitled.html"}]} {
- set thisFile [stripNameCount [lindex [winNames -f] 0]]
- } else {
- return
- }
- }
- return [htmlBASEfromPath $thisFile]
- }
-
- # Returns URL to file.
- proc htmlBASEfromPath {path} {
- global HTMLmodeVars
- foreach p $HTMLmodeVars(homePages) {
- if {(![set i 0] && [string match "[lindex $p $i]:*" "$path:"]) ||
- ([llength $p] == 5 && [set i 4] && [string match "[lindex $p $i]:*" "$path:"])} {
- set path [string range $path [expr [string length [lindex $p $i]] + 1] end]
- regsub -all {:} $path {/} path
- return [list [lindex $p 1] [lindex $p 2] $path [lindex $p 0] $i [lindex $p 4]]
- }
- }
- regsub -all {:} $path {/} path
- return [list "file:///" "" $path "" 0]
- }
-
- # Splits a BASE URL in pieces.
- # NOTE! That this proc returns a shorter list than the proc above, is used in
- # HTMLDblClick to determine if the doc contains a BASE tag.
- proc htmlBASEpieces {href} {
- if {[regexp -indices {://} $href css]} {
- if {[set sl [string first / [string range $href [expr [lindex $css 1] + 1] end]]] >=0} {
- set base [string range $href 0 [expr [lindex $css 1] + $sl + 1]]
- set path [string range $href [expr [lindex $css 1] + $sl + 2] end]
- set sl [string last / $path]
- set epath [string range $path [expr $sl + 1] end]
- set path [string range $path 0 $sl]
- } else {
- set base [string range $href 0 [lindex $css 1]]
- set path ""
- set epath [string range $href [expr [lindex $css 1] + 1] end]
- }
- return [list [htmlURLunEscape $base] [htmlURLunEscape $path] [htmlURLunEscape $epath] ""]
- } else {
- error "Invalid BASE."
- }
- }
-
-
- # Returns toFile including relative path from fromFile.
- proc htmlRelativePath {fromFile toFile} {
- # Remove trailing /file from fromFile
- set fromFile [string range $fromFile 0 [expr [string last / $fromFile] - 1]]
-
- set fromdir [split $fromFile /]
- set todir [split $toFile /]
-
- # Remove the common path.
- set i 0
- while {[llength $fromdir] > $i && [llength $todir] > $i \
- && [lindex $fromdir $i] == [lindex $todir $i]} {
- incr i
- }
-
- # Insert ../
- foreach f [lrange $fromdir $i end] {
- append linkTo "../"
- }
- # Add the path.
- append linkTo [join [lrange $todir $i end] /]
-
- return $linkTo
- }
-
-
- # Returns a list of all HTML files in a folder and its subfolders.
- proc htmlAllHTMLfiles {folder} {
- message "Building file list…"
- set folders [list $folder]
- while {[llength $folders]} {
- set newFolders ""
- foreach fl $folders {
- append files " " [htmlGetHTMLfiles $fl]
- # Get folders in this folder.
- if {![catch {glob "$fl:*"} filelist]} {
- foreach fil $filelist {
- if {[file isdirectory $fil]} {
- lappend newFolders $fil
- }
- }
- }
- }
- set folders $newFolders
- }
- return $files
- }
-
-
- # Finds all HTML files in a folder
- proc htmlGetHTMLfiles {folder} {
- global filepats
- set files ""
- if {![catch {glob -t TEXT $folder:*} filelist]} {
- foreach fil $filelist {
- foreach suffix $filepats(HTML) {
- if {[string match $suffix $fil]} {
- lappend files $fil
- break
- }
- }
- }
- }
- return $files
- }
-
-
- # checking = 1: called from htmlCheckLinks
- # Scan a list of files for HTML links and check if they point to existing files.
- # Some code is taken from grep.tcl
- # checking = 0: called from htmlMoveFiles
- # Build a list of links which point to the files just moved.
- proc htmlScanFiles {files baseURL basePath homepage isInFolder checking filebase {movedFiles ""}} {
- global htmlURLAttr winModes HTMLmodeVars
- global tileLeft tileTop tileWidth errorHeight
- global htmlCaseFolders htmlCaseFiles
-
- set htmlCaseFolders ""; set htmlCaseFiles ""
- set chCase $HTMLmodeVars(caseSensitive)
- set chAnchor $HTMLmodeVars(checkAnchors)
-
- # Build regular expressions with URL attrs.
- set exp "\[ \\t\\n\\r\]+("
- foreach attr $htmlURLAttr {
- append exp "$attr|"
- }
- set exp [string trimright $exp |]
- append exp ")"
-
-
- set expBase "<base\[ \\t\\n\\r\]+\[^>\]*>"
- set expBase2 "(href=)\"?(\[^ \\t\\n\\r\">\]+)\"?"
- # set exprr "$exp\"?(\[^ \\t\\n\\r\">\]+)\"?"
- set exprr "${exp}(\"\[^\">\]+\"|\[^ \\t\\n\\r>\]+)"
- set lines ""
- set toModify ""
-
- foreach f $files {
- if {[catch {set fid [open $f]}]} {continue}
- set base $baseURL
- set path $basePath
- set hpPath $homepage
- if {$isInFolder == ""} {
- set epath $f
- } else {
- set epath [string range $f [expr [string length $isInFolder] + 1] end]
- }
- regsub -all {:} $epath {/} epath
- set baseText ""
- message "Looking at [file tail $f]…"
- set filecont [read $fid]
- close $fid
- if {[regexp {\n} $filecont]} {
- set newln "\n"
- } else {
- set newln "\r"
- }
- # Look for BASE.
- if {[regexp -nocase $expBase $filecont thisLine]} {
- if {[regexp -nocase $expBase2 $thisLine href b url]} {
- if {![catch {htmlBASEpieces $url} basestr]} {
- set base [lindex $basestr 0]
- set path [lindex $basestr 1]
- set epath [lindex $basestr 2]
- set hpPath ""
- set baseText "(BASE used) "
- } else {
- set baseText "(Invalid BASE) "
- }
- }
- }
- set linenum 1
- # Find all links in every line.
- while {[regexp -nocase -indices $exprr $filecont href b url]} {
- incr linenum [regsub -all $newln [string range $filecont 0 [lindex $url 0]] {} dummy]
- set linkTo [htmlURLunEscape [string trim [string range $filecont [lindex $url 0] [lindex $url 1]] \"]]
- set nogood 0
- if {[catch {htmlPathToFile $base $path $epath $hpPath $linkTo} linkToPath]} {
- if {$linkToPath == ""} {
- set nogood 1
- }
- set linkToPath ""
- } else {
- # Anchors always point to the file itself, unless there's a BASE.
- if {[string index $linkTo 0] == "#" && $baseText == ""} {set linkToPath [list $f $f]}
- set casePath [lindex $linkToPath 1]
- set linkToPath [lindex $linkToPath 0]
- }
- # If this is BASE HREF, ignore it.
- if {[string length $baseText] && [regexp -nocase -indices $expBase $filecont thisLine] \
- && [regexp -nocase $expBase2 [string range $filecont [lindex $thisLine 0] [lindex $thisLine 1]]]\
- && [lindex $thisLine 0] < [lindex $url 0] && [lindex $thisLine 1] > [lindex $url 1]} {
- set linkToPath ""
- }
- if {$checking} {
- set anchorCheck 1
- set caseOK 1
- set fext [file exists $linkToPath]
- if {$chAnchor && $linkToPath != "" && [regexp {#} $linkTo] && $fext} {set anchorCheck [htmlCheckAnchor $linkToPath $linkTo]}
- if {$chCase && $linkToPath != "" && $fext} {set caseOK [htmlCheckLinkCase $linkToPath $casePath]}
- # Does the file exist? Ignore it if it's outside home page folder.
- # Then it point to someone else's home page.
- if {!$anchorCheck || $nogood || !$caseOK || ( $linkToPath != "" && !$fext)} {
- set bText $baseText
- if {!$anchorCheck} {append bText "(anchor missing) "}
- if {!$caseOK} {append bText "(case doesn't match) "}
- if {$homepage == ""} {
- append lines [string range $f $filebase end]
- } else {
- append lines [string range $f [expr [string length $isInFolder] + 1] end]
- }
- set l [expr 20 - [string length [file tail $f]]]
- set ln [expr 5 - [string length $linenum]]
- set href [string trim [string range $filecont [lindex $href 0] [lindex $href 1]]]
- append lines "[format "%$l\s" ""]; Line $linenum:[format "%$ln\s" ""]$bText$href"\
- "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$f\r"
- }
- } elseif {[lsearch -exact $movedFiles $linkToPath] >=0 } {
- set href [string trim [string range $filecont [lindex $href 0] [lindex $href 1]]]
- lappend toModify [list $f $linenum $base $path $epath $linkToPath $href]
- }
- set filecont [string range $filecont [lindex $url 1] end]
- }
- }
-
- unset htmlCaseFolders htmlCaseFiles
- message ""
- if {$checking} {
- if {[string length $lines]} {
- new -n "* Invalid URLs *" -g $tileLeft $tileTop $tileWidth $errorHeight
- set name [lindex [winNames] 0]
- changeMode [set winModes($name) Brws]
- insertText "Incorrect links: (<uparrow> and <downarrow> to browse, <return> to go to file)\r\r$lines"
- select [nextLineStart [nextLineStart 0]] [nextLineStart [nextLineStart [nextLineStart 0]]]
- setWinInfo dirty 0
- setWinInfo read-only 1
- scrollUpLine; scrollUpLine
- } else {
- alertnote "All links are OK."
- }
- } else {
- return $toModify
- }
- }
-
-
- # Determine the path to the file "linkTo", as linked from "base path epath".
- proc htmlPathToFile {base path epath hpPath linkTo} {
- global HTMLmodeVars
-
- # Is this a mailto or news URL or anchor?
- if {[string match "mailto:*" [string tolower $linkTo]] ||
- [string match "news:*" [string tolower $linkTo]]} {
- error $linkTo
- }
-
- # remove /file from epath
- set sl [string last / $epath]
- set efil [string range $epath [expr $sl + 1] end]
- set epath [string range $epath 0 $sl]
-
- # anchor points to efil
- if {[string index $linkTo 0] == "#"} {set linkTo $efil}
-
- # Remove anchor from "linkTo".
- regexp {[^#]*} $linkTo linkTo
-
- # Remove ./ from path
- if {[string range $linkTo 0 1] == "./"} {set linkTo [string range $linkTo 2 end]}
-
- # Relative URL beginning with / is relative to server URL.
- if {[string index $linkTo 0] == "/"} {
- set linkTo "$base[string range $linkTo 1 end]"
- }
-
- # Relative URL?
- if {![regexp {://} $linkTo]} {
- set fromPath [split [string trimright "${path}$epath" /] /]
- set toPath [split $linkTo /]
- # Back down for every ../
- set i 0
- foreach tp $toPath {
- if {$tp == ".."} {
- incr i
- } else {
- break
- }
- }
- if {$i > [llength $fromPath] } {
- error ""
- } else {
- set path1 [join [lrange $fromPath 0 [expr [llength $fromPath] - $i - 1]] /]
- if {[string length $path1]} {append path1 /}
- append path1 [join [lrange $toPath $i end] /]
- if {[string match "$path*" $path1] && [string length $hpPath]} {
- set pathTo [string range $path1 [string length $path] end]
- regsub -all {/} $pathTo {:} pathTo
- set casePath $pathTo
- set pathTo "$hpPath:$pathTo"
- if {![file isdirectory $pathTo]} {return [list $pathTo $casePath]}
- } elseif {$base == "file:///"} {
- regsub -all {/} $path1 {:} pathTo
- return [list $pathTo $pathTo]
- }
- set linkTo "$base$path1"
- }
- }
-
- foreach hp [concat $HTMLmodeVars(homePages) {{"" file:/// "" ""}}] {
- if {[string match "[lindex $hp 1][lindex $hp 2]*" $linkTo] ||
- [string trimright "[lindex $hp 1][lindex $hp 2]" /] == $linkTo} {
- set pathTo [string range $linkTo [string length "[lindex $hp 1][lindex $hp 2]"] end]
- regsub -all {/} $pathTo {:} pathTo
- set casePath $pathTo
- set pathTo [string trimleft "[lindex $hp 0]:$pathTo" :]
- # If link to folder, add default file.
- if {[file isdirectory $pathTo]} {
- set pathTo [string trimright $pathTo :]
- append pathTo ":[lindex $hp 3]"
- set casePath [string trimright $casePath :]
- append casePath ":[lindex $hp 3]"
- }
- return [list $pathTo [string trimleft $casePath :]]
- }
- }
- error $linkTo
- }
-
-
- proc htmlCheckAnchor {anchorFile url} {
- regexp {[^#]*#(.*)} $url dum anchor
- if {[catch {open $anchorFile r} fid]} {return 1}
- set filecont [read $fid]
- close $fid
- set exp "<(\[Aa\]|\[mM\]\[aA\]\[pP\])\[ \t\r\n\]+\[^>\]*\[nN\]\[aA\]\[mM\]\[eE\]=\"?$anchor\"?(>|\[ \t\r\n\]+\[^>\]*>)"
- return [regexp $exp $filecont]
- }
-
- # Checks that the case in a link match the case in the path to file.
- proc htmlCheckLinkCase {path link} {
- global htmlCaseFolders htmlCaseFiles
-
- set path [string trimright $path :]
- set link [string trimright $link :]
- if {[lsearch -exact $htmlCaseFiles $path] >= 0} {return 1}
- set path [split $path :]
- set plen [llength $path]
- set llen [llength [split $link :]]
- set j [expr $plen - $llen ? $plen - $llen - 1 : 0]
- for {set i $j} {$i < $plen - 1} {incr i} {
- set l [lindex $path [expr $i + 1]]
- set psub [join [lrange $path 0 $i] :]
- if {[lsearch -exact $htmlCaseFolders $psub] < 0} {
- lappend htmlCaseFolders $psub
- append htmlCaseFiles " " [glob -nocomplain "$psub:*"]
- }
- if {[lsearch -exact $htmlCaseFiles "$psub:$l"] < 0} {return 0}
- }
- return 1
- }
-
- #
- # Carriage returns and tabs (much borrowed from latex.tcl)
- #
-
- # A boolean function which takes any string and tests to see if
- # that string contains all whitespace characters. Carriage returns
- # are considered whitespace, as are spaces and tabs.
- proc htmlIsWhite {anyString} {
- return [regexp {^[ \t\r]*$} $anyString]
- }
-
- # Insert one or two carriage returns at the insertion point if any
- # character preceding the insertion point (on the same line)
- # is a non-whitespace character.
- proc htmlOpenCR {{extrablankline 0}} {
- set end [getPos]
- set start [lineStart $end]
- set text [getText $start $end]
- if {![htmlIsWhite $text]} {
- set r "\r"
- if {$extrablankline} {append r "\r"}
- return $r
- } elseif {$start > 0 } {
- set prevstart [lineStart [expr $start - 1 ]]
- set text [getText $prevstart [expr $start - 1]]
- if {![htmlIsWhite $text] && $extrablankline} {
- return "\r"
- } else {
- return
- }
- } else {
- return
- }
- }
-
- # Insert a carriage return at the insertion point if any
- # character following the insertion point (on the same line)
- # is a non-whitespace character.
- proc htmlCloseCR {} {
- set start [getPos]
- if {![htmlIsWhite [getText $start [nextLineStart $start]]]} {
- return "\r"
- } else {
- return
- }
- }
-
- # Set up tab mark mechanism.
- proc htmlTabGoto {directionIndicator} {
- set searchResult [search -s -n -f $directionIndicator -m 0 -i 1 -r 0 {•} [getPos]]
- if {![llength $searchResult] || [lindex $searchResult 0] >= [maxPos]} {
- beep
- message "Tab mark not found."
- return 0
- } else {
- goto [lindex $searchResult 0]
- return 1
- }
- }
-
- proc htmlTabNext {} {
- if {[htmlTabGoto 1]} {deleteChar}
- }
-
- proc htmlTabPrev {} {
- if {[htmlTabGoto 0]} {deleteChar}
- }
-
- # Puts up a window with error text.
-
- proc htmlErrorWindow {errHeader errText {cancelButton 0}} {
-
- set errbox "-t {$errHeader} 100 10 400 25"
- set hpos 35
- foreach err $errText {
- lappend errbox -t $err 10 $hpos 400 [expr $hpos + 15]
- incr hpos 20
- }
- if {$cancelButton} {
- lappend errbox -b Cancel 105 [expr $hpos + 20 ] 170 [expr $hpos + 40 ]
- }
-
- set val [eval [concat dialog -w 430 -h [expr $hpos + 50 ] \
- -b OK 20 [expr $hpos + 20 ] 85 [expr $hpos + 40 ] $errbox]]
- return [lindex $val 0]
- }
-
-
- #===============================================================================
- # Building tags, including element attributes
- #===============================================================================
-
- # A couple of functions to get element variables from the right package.
- proc htmlGetSomeAttrs {item type num1 pkg} {
- global htmlElem${type}$num1 htmlElem${type}3
- if {[catch {set atts [set htmlElem${type}${pkg}($item)]}]} {
- if {$type == "AttrMore"} {
- set atts 0
- } else {
- set atts {}
- }
- }
- return $atts
- }
-
- proc htmlGetRequired {item} {
- global htmlPackageToUse
- return [htmlGetSomeAttrs $item AttrRequired 1 $htmlPackageToUse]
- }
-
- proc htmlGetOptional {item} {
- global htmlPackageToUse
- return [htmlGetSomeAttrs $item AttrOptional 1 $htmlPackageToUse]
- }
-
- proc htmlGetNumber {item} {
- global htmlPackageToUse
- return [htmlGetSomeAttrs $item AttrNumber 1 $htmlPackageToUse]
- }
-
-
- proc htmlGetChoices {item} {
- global htmlPackageToUse
- return [htmlGetSomeAttrs $item AttrChoices 1 $htmlPackageToUse]
- }
-
- proc htmlGetUsed {item} {
- global htmlPackageToUse
- if {$htmlPackageToUse == 1} {
- set num ""
- } else {
- set num 3
- }
- return [htmlGetSomeAttrs $item AttrUsed "" $num]
- }
-
- proc htmlGetAttrMore {item} {
- global htmlPackageToUse
- if {$htmlPackageToUse == 1} {
- set num ""
- } else {
- set num 3
- }
- return [htmlGetSomeAttrs $item AttrMore "" $num]
- }
-
- proc htmlOpenElem {elem {used ""} {pos -1}} {
- global HTMLmodeVars
- if {$HTMLmodeVars(useBigWindows)} {
- return [htmlOpenElemWindow $elem $used $pos]
- } else {
- return [htmlOpenElemLoop $elem $used $pos]
- }
- }
-
- # Opening or only tag of an element - include attributes
- # Big window with all attributes.
- # Return empty string if user clicks "Cancel".
-
- proc htmlOpenElemWindow {elem used wrPos {values ""}} {
- global HTMLmodeVars htmlColorName htmlElemEventHandler1
- global htmluserColors basicColors htmlPackageToUse
- global htmlURLAttr htmlColorAttr htmlWindowAttr
- global htmlSpecURL htmlSpecColor htmlSpecWindow htmlWrapPos
-
- set URLs $HTMLmodeVars(URLs)
- set Windows $HTMLmodeVars(windows)
-
- # put users colours first
- set htmlColors [lsort [array names htmluserColors]]
- append htmlColors " " $basicColors
-
- if {![string length $used]} {set used $elem}
- set elem [string toupper $elem]
- set used [string toupper $used]
-
- # get variables for the element
- set reqatts [htmlGetRequired $used]
- set numatts [htmlGetNumber $used]
- set optatts [htmlGetOptional $used]
- set choiceatts [htmlGetChoices $used]
-
- set allatts [concat $reqatts $optatts]
-
- # optionally include event handlers
- if {$HTMLmodeVars(inclEventHandler) && $htmlPackageToUse == 1 && \
- [info exists htmlElemEventHandler1($used)]} {
- set eventatts $htmlElemEventHandler1($used)
- append allatts " " $eventatts
- } else {
- set eventatts ""
- }
-
- # if there are attributes to ask about, do so
-
- set text "<"
- append text [htmlSetCase $elem]
- if {![llength $allatts]} {return "$text>"}
-
- set maxHeight [expr [lindex [getMainDevice] 3] - 115]
- set thisPage "Page 1"
-
-
- # build window with attributes
- set invalidInput 1
- while {$invalidInput} {
- # wrapping
- set htmlWrapPos [expr $wrPos == -1 ? [lindex [posToRowCol [getPos]] 1] : $wrPos]
- incr htmlWrapPos [expr [string length $text] + 1]
- while {1} {
- if {$used == "LI IN UL" || $used == "LI IN OL"} {
- set pr LI
- } else {
- set pr $used
- }
- set box1 "-t {Attributes for $pr} 120 10 450 25"
- set box2 "-t {Attributes for $pr} 120 10 450 25"
- set box3 "-t {Attributes for $pr} 120 10 450 25"
- set page 1
- set attrtypes {}
- set fileIndex ""
- set colorIndex ""
- set wpos 10
- if {[string length $reqatts]} {
- lappend box$page -p 120 30 270 31 -t {Required attributes} 10 35 200 50
- set hpos 60
- } else {
- set hpos 30
- }
- set attrIndex 2
- for {set i 0} {$i < [llength $allatts]} {incr i} {
- set attr [lindex $allatts $i]
- if {$i == [llength $reqatts]} {
- if {$wpos > 20} { incr hpos 20 }
- lappend box$page -p 120 $hpos 270 [expr $hpos + 1] \
- -t {Optional attributes} 10 [expr $hpos + 5] 200 [expr $hpos + 20]
- set wpos 10
- incr hpos 30
- }
- set a2 [string trimright $attr =]
- if {[string index $attr [expr [string length $attr] - 1]] != "="} {
- # Flag
- if {[expr $hpos + 20] > $maxHeight && $wpos < 20 && $page < 3} {
- incr page
- set hpos 40
- }
- if {[llength values]} {
- set ctxt [lindex $values $attrIndex]
- incr attrIndex
- } else {
- set ctxt 0
- }
- lappend box$page -c $attr $ctxt $wpos $hpos [expr $wpos + 100] [expr $hpos + 15]
- if {$wpos > 20} {
- incr hpos 25
- set wpos 10
- } else {
- set wpos 230
- }
- lappend attrtypes flag
- } elseif {([lsearch -exact $htmlURLAttr $attr] >= 0 && [lsearch -exact $htmlSpecURL "${used}!=$a2"] < 0) || \
- [lsearch -exact $htmlSpecURL "${used}=$a2"] >= 0} {
- # URL
- if {$wpos > 20} { incr hpos 25 ; set wpos 10}
- if {[expr $hpos + 45] > $maxHeight && $page < 3} {
- incr page
- set hpos 40
- }
- if {[llength values]} {
- set etxt [lindex $values $attrIndex]
- set mtxt [lindex $values [expr $attrIndex + 1]]
- incr attrIndex 3
- } else {
- set etxt ""
- set mtxt {No value}
- }
- lappend box$page -t $attr 10 $hpos 120 [expr $hpos + 15] \
- -e $etxt 120 $hpos 450 [expr $hpos + 15] \
- -m [concat [list $mtxt {No value}] $URLs] \
- 120 [expr $hpos + 25] 450 [expr $hpos + 35] \
- -b "File…" 10 [expr $hpos + 20] 70 [expr $hpos + 40]
- incr hpos 50
- lappend attrtypes url
- lappend fileIndex [expr $attrIndex - 1]
- } elseif {([lsearch -exact $htmlColorAttr $attr] >= 0 && [lsearch -exact $htmlSpecColor "${used}!=$a2"] < 0) || \
- [lsearch -exact $htmlSpecColor "${used}=$a2"] >= 0} {
- # Color attribute
- if {$wpos > 20} { incr hpos 25 ; set wpos 10}
- if {[expr $hpos + 25] > $maxHeight && $page < 3} {
- incr page
- set hpos 40
- }
- if {[llength values]} {
- set etxt [lindex $values $attrIndex]
- set mtxt [lindex $values [expr $attrIndex + 1]]
- incr attrIndex 3
- } else {
- set etxt ""
- set mtxt {No value}
- }
- lappend box$page -t $attr 10 $hpos 120 [expr $hpos + 15] \
- -e $etxt 120 $hpos 190 [expr $hpos + 15] \
- -m [concat [list $mtxt {No value}] $htmlColors] \
- 200 $hpos 340 [expr $hpos + 15] \
- -b "New Color…" 350 $hpos 450 [expr $hpos + 20]
- incr hpos 30
- lappend attrtypes color
- lappend colorIndex [expr $attrIndex - 1]
- } elseif {([lsearch -exact $htmlWindowAttr $attr] >= 0 && [lsearch -exact $htmlSpecWindow "${used}!=$a2"] < 0) || \
- [lsearch -exact $htmlSpecWindow "${used}=$a2"] >= 0} {
- # Window attribute
- if {$wpos > 20} { incr hpos 25 ; set wpos 10}
- if {[expr $hpos + 25] > $maxHeight && $page < 3} {
- incr page
- set hpos 40
- }
- if {[llength values]} {
- set etxt [lindex $values $attrIndex]
- set mtxt [lindex $values [expr $attrIndex + 1]]
- incr attrIndex 2
- } else {
- set etxt ""
- set mtxt {No value}
- }
- lappend box$page -t $attr 10 $hpos 120 [expr $hpos + 15] \
- -e $etxt 120 $hpos 240 [expr $hpos + 15] \
- -m [concat [list $mtxt {No value}] \
- [concat {_self _top _parent _blank} $Windows]] \
- 250 $hpos 440 [expr $hpos + 15]
- incr hpos 30
- lappend attrtypes window
- } elseif {[lsearch $numatts "${attr}*"] >= 0} {
- # Number
- if {[expr $hpos + 20] > $maxHeight && $wpos < 20 && $page < 3} {
- incr page
- set hpos 40
- }
- if {[llength values]} {
- set etxt [lindex $values $attrIndex]
- incr attrIndex
- } else {
- set etxt ""
- }
- lappend box$page -t $attr $wpos $hpos [expr $wpos + 100] [expr $hpos + 15] \
- -e $etxt [expr $wpos + 110] $hpos [expr $wpos + 150] [expr $hpos + 15]
- if {$wpos > 20} {
- incr hpos 25
- set wpos 10
- } else {
- set wpos 230
- }
- lappend attrtypes number
- } elseif {[lsearch $choiceatts "${attr}*"] >= 0} {
- # Choices
- if {[expr $hpos + 20] > $maxHeight && $wpos < 20 && $page < 3} {
- incr page
- set hpos 40
- }
- set matches {}
- foreach w $choiceatts {
- if {[string match "${attr}*" $w]} {
- lappend matches [string range $w [string length $attr] end]
- }
- }
- if {[llength values]} {
- set mtxt [lindex $values $attrIndex]
- incr attrIndex
- } else {
- set mtxt {No value}
- }
- lappend box$page -t $attr $wpos $hpos [expr $wpos + 100] [expr $hpos + 15] \
- -m [concat [list $mtxt {No value}] $matches] \
- [expr $wpos + 110] $hpos [expr $wpos + 205] [expr $hpos + 15]
- if {$wpos > 20} {
- incr hpos 25
- set wpos 10
- } else {
- set wpos 230
- }
- lappend attrtypes choices
- } else {
- # Any other
- if {$wpos > 20} { incr hpos 25 ; set wpos 10}
- if {[expr $hpos + 20] > $maxHeight && $page < 3} {
- incr page
- set hpos 40
- }
- if {[llength values]} {
- set etxt [lindex $values $attrIndex]
- incr attrIndex
- } else {
- set etxt ""
- }
- lappend box$page -t $attr 10 $hpos 120 [expr $hpos + 15] \
- -e $etxt 120 $hpos 450 [expr $hpos + 15]
- incr hpos 25
- lappend attrtypes any
- }
- }
- if {$wpos > 20} { incr hpos 25 }
-
- if {$page == 1} {
- set box $box1
- } elseif {$page == 2} {
- set hpos $maxHeight
- set box " -m \{\{$thisPage\} \{Page 1\} \{Page 2\}\} 10 10 85 30 -n \{Page 1\} $box1 -n \{Page 2\} $box2"
- } elseif {$page == 3} {
- set hpos $maxHeight
- set box " -m \{\{$thisPage\} \{Page 1\} \{Page 2\} \{Page 3\}\} 10 10 85 30 -n \{Page 1\} $box1 -n \{Page 2\} $box2 -n \{Page 3\} $box3"
- }
- set values [eval [concat dialog -w 460 -h [expr $hpos + 50] \
- -b OK 20 [expr $hpos + 20] 85 [expr $hpos + 40] \
- -b Cancel 110 [expr $hpos + 20] 175 [expr $hpos + 40] $box]]
- # If two pages...
- if {$page > 1} {
- set thisPage [lindex $values 2]
- set values [lreplace $values 2 2]
- }
-
- # OK button clicked?
- if {[lindex $values 0] } { break }
- # Cancel button clicked?
- if {[lindex $values 1] } { return}
- # File button clicked?
- foreach fl $fileIndex {
- if {[lindex $values $fl]} {
- set newFile [htmlGetFile]
- if {[string length $newFile]} {
- set URLs $HTMLmodeVars(URLs)
- set values [lreplace $values [expr $fl - 1] [expr $fl - 1] [lindex $newFile 0]]
- if {$used == "IMG" && $fl == 4 && [llength [set widhei [lindex $newFile 1]]]} {
- set nnn [expr $htmlPackageToUse == 1 ? 8 : 5]
- set values [lreplace $values $nnn $nnn [lindex $widhei 0]]
- set values [lreplace $values [expr $nnn + 1] [expr $nnn + 1] [lindex $widhei 1]]
- }
- }
- }
- }
- # Color button clicked?
- foreach cl $colorIndex {
- if {[lindex $values $cl]} {
- set newcolor [htmlAddNewColor]
- if {[string length $newcolor]} {
- set htmlColors [concat [list $newcolor] $htmlColors]
- set values [lreplace $values [expr $cl - 1] [expr $cl - 1] "$newcolor"]
- }
- }
- }
- }
-
-
- # put everything together
- set attrtext ""
- set errtext ""
- if {[lindex $values 0]} {
- set j 2
- for {set i 0} {$i < [llength $attrtypes]} {incr i} {
- set attr [lindex $allatts $i]
- switch [lindex $attrtypes $i] {
- url {
- set texturl [string trim [lindex $values $j]]
- set menuurl [lindex $values [expr $j + 1]]
- if {[string length $texturl]} {
- append attrtext [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes [htmlURLescape2 $texturl]]"]
- htmlAddToCache URLs $texturl
- } elseif {$menuurl != "No value"} {
- append attrtext [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes [htmlURLescape2 $menuurl]]"]
- } elseif {[lsearch -exact $reqatts $attr] >= 0} {
- lappend errtext "$attr required."
- }
- incr j 3
- }
- color {
- set colortxt [lindex $values $j]
- set colorval [lindex $values [expr $j + 1]]
- if {[string length $colortxt]} {
- set col [htmlCheckColorNumber $colortxt]
- if {$col == 0} {
- lappend errtext "$attr: $colortxt is not a valid color number."
- } else {
- append attrtext [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes $col]"]
- }
- } elseif {$colorval != "No value"} {
- # Users own color?
- if {[info exists htmluserColors($colorval)]} {
- set colornum $htmluserColors($colorval)
- }
- # Predefined color?
- if {[info exists htmlColorName($colorval)]} {
- set colornum $htmlColorName($colorval)
- }
- append attrtext [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes $colornum]"]
- } elseif {[lsearch -exact $reqatts $attr] >= 0} {
- lappend errtext "$attr required."
- }
- incr j 3
- }
- window {
- set textwin [string trim [lindex $values $j]]
- set menuwin [lindex $values [expr $j + 1]]
- if {[string length $textwin]} {
- append attrtext [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes $textwin]"]
- htmlAddToCache windows $textwin
- } elseif {$menuwin != "No value"} {
- append attrtext [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes $menuwin]"]
- } elseif {[lsearch -exact $reqatts $attr] >= 0} {
- lappend errtext "$attr required."
- }
- incr j 2
- }
- number {
- set numval [string trim [lindex $values $j]]
- if {[string length $numval]} {
- if {[htmlCheckAttrNumber $used $attr $numval] == 1} {
- append attrtext [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes $numval]"]
- } else {
- lappend errtext "$attr: [htmlCheckAttrNumber $used $attr $numval]"
- }
- } elseif {[lsearch -exact $reqatts $attr] >= 0} {
- lappend errtext "$attr required."
- }
- incr j
- }
- choices {
- set choiceval [lindex $values $j]
- if {$choiceval != "No value"} {
- set qchoice [htmlAddQuotes $choiceval]
- if {($used != "LI IN OL" && $used != "OL") || $attr != "TYPE="} {
- set qchoice [htmlSetCase $qchoice]
- }
- append attrtext [htmlWrapTag "[htmlSetCase $attr]$qchoice"]
- } elseif {[lsearch -exact $reqatts $attr] >= 0} {
- lappend errtext "$attr required."
- }
- incr j
- }
- any {
- set anyval [lindex $values $j]
- # Trim only if it's only spaces.
- if {[string trim $anyval] == ""} {set anyval ""}
- if {[string length $anyval]} {
- htmlOpenExtraThings $used $attr $anyval
- if {[lsearch -exact $eventatts $attr] < 0} {
- set attr [htmlSetCase $attr]
- }
- append attrtext [htmlWrapTag "$attr[htmlAddQuotes $anyval]"]
- } elseif {[lsearch -exact $reqatts $attr] >= 0} {
- lappend errtext "$attr required."
- }
- incr j
- }
- flag {
- set flagval [lindex $values $j]
- if {$flagval} {
- append attrtext [htmlWrapTag [htmlSetCase $attr]]
- }
- incr j
- }
- }
- }
- # If everything is OK, add the attribute text to text.
- if {![llength $errtext]} {
- append text $attrtext
- set invalidInput 0
- } else {
- # Put up alert with the error text.
- htmlErrorWindow "Invalid input for $used" $errtext
- }
- # Some tests that input is ok.
- if {!$invalidInput} {set invalidInput [htmlFontBaseTest $text alertnote]}
- if {!$invalidInput && $elem == "A" && [set invalidInput [htmlATest $text alertnote]]} {
- set text "<[htmlSetCase A]"
- }
- if {!$invalidInput && $elem == "FRAMESET" && [set invalidInput [htmlFramesetTest $text alertnote]]} {
- set text "<[htmlSetCase FRAMESET]"
- }
- if {!$invalidInput && $elem == "SPACER" && [set invalidInput [htmlSpacerTest $text alertnote]]} {
- set text "<[htmlSetCase SPACER]"
- }
- if {!$invalidInput && $elem == "AREA" && [set invalidInput [htmlAreaTest $text alertnote]]} {
- set text "<[htmlSetCase AREA]"
- }
- } else {
- set text ""
- }
- }
-
- if {[string length $text] } {append text ">"}
-
- return ${text}
- }
-
- proc htmlWrapTag {toadd} {
- global htmlWrapPos fillColumn HTMLmodeVars
- if {!$HTMLmodeVars(wordWrap)} {return " $toadd"}
- incr htmlWrapPos [string length $toadd]
- if {$htmlWrapPos > $fillColumn} {
- set htmlWrapPos [string length $toadd]
- return "\r$toadd"
- } else {
- return " $toadd"
- }
- }
-
- # these two require at least one of several optional attributes
- proc htmlFontBaseTest {text cmd} {
- if {([string toupper $text] == "<FONT" || [string toupper $text] == "<BASE" )} {
- eval {$cmd "At least one of the attributes is required."}
- return 1
- }
- return 0
- }
-
- # HREF or NAME must be used for A.
- proc htmlATest {text cmd} {
- if {![regexp -nocase {href=} $text] && ![regexp -nocase {name=} $text]} {
- eval {$cmd "At least one of the attributes HREF and NAME must be used."}
- return 1
- }
- return 0
- }
-
- # ROWS or COLS must be used for FRAMESET
- proc htmlFramesetTest {text cmd} {
- if {![regexp -nocase {rows=} $text] && ![regexp -nocase {cols=} $text]} {
- eval {$cmd "At least one of the attributes ROWS and COLS must be used."}
- return 1
- }
- return 0
- }
-
- # Some checks for SPACER.
- proc htmlSpacerTest {text cmd} {
- set horver [regexp -nocase {type=\"(horizontal|vertical)\"} $text]
- set wh [regexp -nocase {width=|height=} $text]
- set sz [regexp -nocase {size=} $text]
- set al [regexp -nocase {align=} $text]
- set invalidInput 1
- if {$horver && ($wh || $al)} {
- eval {$cmd "WIDTH, HEIGHT and ALIGN should only be used when TYPE=BLOCK."}
- } elseif {!$horver && $sz} {
- eval {$cmd "SIZE should only be used when TYPE=HORIZONTAL or VERTICAL."}
- } elseif {$horver && !$sz} {
- eval {$cmd "SIZE is required when TYPE=HORIZONTAL or VERTICAL."}
- } elseif {!$horver && !$wh} {
- eval {$cmd "WIDTH or HEIGHT is required when TYPE=BLOCK."}
- } else {
- set invalidInput 0
- }
- return $invalidInput
- }
-
- # For AREA, either HREF or NOHREF must be used, but not both.
- proc htmlAreaTest {text cmd} {
- set hasHref [regexp -nocase {href=} $text]
- set hasNohref [regexp -nocase {nohref} $text]
- set hasCoords [regexp -nocase {coords=} $text]
- set shapeDefault [regexp -nocase {shape=\"default\"} $text]
- set invalidInput 0
- if {($hasHref && $hasNohref) || (!$hasHref && !$hasNohref)} {
- eval {$cmd "One of the attributes HREF and NOHREF must be used, but not both."}
- set invalidInput 1
- } elseif {!$hasCoords && !$shapeDefault} {
- eval {$cmd "COORDS= is required if SHAPE≠DEFAULT"}
- set invalidInput 1
- }
- return $invalidInput
- }
-
- # Adds a NAME= value to cache.
- proc htmlOpenExtraThings {elem attr val} {
- if {[lsearch -exact {A MAP} $elem] >= 0 && $attr == "NAME="} {
- htmlAddToCache URLs "#$val"
- }
- if {$elem == "FRAME" && $attr == "NAME="} {
- htmlAddToCache windows $val
- }
- }
-
-
- # Check if a color number is a valid number, or one of the predefined names.
- # Returns 0 if not and the color number if it is.
- proc htmlCheckColorNumber {color} {
- global htmlColorName
- set color [string tolower $color]
- if {[info exists htmlColorName($color)]} {return $htmlColorName($color)}
- if {[string index $color 0] != "#"} {
- set color "#${color}"
- }
- set color [string toupper $color]
- if {[string length $color] != 7 || ![regexp {^#[0-9A-F]+$} $color]} {
- return 0
- } else {
- return $color
- }
- }
-
-
- # Adds a URL or window given as input to cache
- proc htmlAddToCache {cache newurl} {
- global modifiedModeVars HTMLmodeVars
-
- if {$cache == "windows" && [lsearch -exact {_self _top _parent _blank} $newurl] >= 0} {return}
- set URLs $HTMLmodeVars($cache)
-
- if {[string length $newurl] && [lsearch -exact $URLs $newurl] < 0} {
- set URLs [lsort [lappend URLs $newurl]]
- set HTMLmodeVars($cache) $URLs
- lappend modifiedModeVars [list $cache HTMLmodeVars]
- if {[llength $URLs] == 1} {htmlEnable$cache on}
- }
- }
-
- # Check if a input is a valid number for the element attribute.
- # Returns 1 if it is, otherwise returns an error message.
- proc htmlCheckAttrNumber {item attr number} {
-
- set attrNumbers [htmlGetNumber $item]
- set numind [lsearch $attrNumbers "${attr}*"]
- set numstr [string range [lindex $attrNumbers $numind] [string length $attr] end]
- regexp {^[-0-9]+} $numstr minvalue
- set numstr [string range $numstr [expr [string length $minvalue] + 1] end]
- regexp {^[-i0-9]+} $numstr maxvalue
- set procent [string range $numstr [expr [string length $numstr] - 1] end]
- if {$procent == "%"} {
- set procerr " or percentage"
- } else {
- set procerr ""
- }
- if {$maxvalue == "i"} {
- set errtext "A number $minvalue or greater"
- } else {
- set errtext "A number in the range $minvalue to $maxvalue"
- }
- if {$item == "FONT"} { append errtext " or -6 to +6"}
- append errtext "$procerr expected."
- # Is percent allowed?
- if {[string index $number [expr [string length $number] - 1]] == "%" } {
- set number [string range $number 0 [expr [string length $number] - 2]]
- if {$procent != "%"} {return $errtext}
- }
- # FONT can take values -6 - +6. Special case.
- if {$item == "FONT" && [regexp {^(\+|-)[1-6]$} $number]} { return 1}
- # Is input a number?
- if {![regexp {^-?[0-9]+$} $number]} {return $errtext}
- # Is input in the valid range?
- if {( $maxvalue != "i" && $number > $maxvalue ) || $number < $minvalue } {
- return $errtext
- }
- return 1
- }
-
-
- # Add quotes to attribute
- proc htmlAddQuotes {v} {
-
- if {[string range $v 0 0] != "\""} {set v "\"$v"}
- set vlen [expr [string length $v] - 1]
- if {[string range $v $vlen $vlen] !="\""} {append v "\""}
- return $v
- }
-
-
- # Splits an attribute into its name and value and remove quotes.
- proc htmlRemoveQuotes {attrStr} {
- # Is it a flag?
- if {![string match "*=*" $attrStr]} {return [string toupper $attrStr]}
-
- set attr [string range $attrStr 0 [string first "=" $attrStr]]
- # Get the attribute value.
- set attrVal [string range $attrStr [expr [string first "=" $attrStr] + 1] end]
-
- return [list $attr [string trim $attrVal \"]]
- }
-
-
- # Closing tag of an element
- proc htmlCloseElem {theElem} {
- return "</[htmlSetCase $theElem]>"
- }
-
-
- #
- # Element build routines
- #
-
- # Build elements with only a opening tag.
- proc htmlBuildOpening {ftype {begCR 0} {endCR 0} {attr ""}} {
- set text1 ""
- if {$begCR} { set text1 [htmlOpenCR]}
- set text [htmlOpenElem $ftype $attr]
- if {![string length $text]} {return}
- if {$endCR} {append text "\r"}
- insertText $text1 $text
- }
-
-
- # This is used for almost all containers
- proc htmlBuildElem {ftype {attr ""}} {
- global HTMLmodeVars htmlCurSel htmlIsSel
-
- if {![string length [set text [htmlOpenElem $ftype $attr]]]} {return}
- htmlGetSel
- append text $htmlCurSel
- set currpos [expr [getPos] + [string length $text]]
- append text [htmlCloseElem $ftype]
- if {!$htmlIsSel && $HTMLmodeVars(useTabMarks)} {append text "•"}
- if {$htmlIsSel} {
- replaceText [getPos] [selEnd] $text
- } else {
- insertText $text
- goto $currpos
- }
- }
-
- # This is used for elements that should be surrounded by newlines
- proc htmlBuildCRElem {ftype {extrablankline 0} {attr ""}} {
- global htmlCurSel htmlIsSel HTMLmodeVars
-
- set text [htmlOpenCR $extrablankline]
-
- if {![string length [set text2 [htmlOpenElem $ftype $attr 0]]]} {return}
- append text $text2
- htmlGetSel
- append text $htmlCurSel
- set currpos [expr [getPos] + [string length $text]]
- append text [htmlCloseElem $ftype]
- append text "\r"
- if {$extrablankline} {append text "\r"}
- if {!$htmlIsSel && $HTMLmodeVars(useTabMarks)} {append text "•"}
- if {$htmlIsSel} { deleteSelection }
- insertText $text
- if {!$htmlIsSel} {
- goto $currpos
- }
- }
-
- # This is used for elements that should be surrounded by empty lines
- proc htmlBuildCR2Elem {ftype {attr ""}} {
- global HTMLmodeVars htmlCurSel htmlIsSel
-
- set text [htmlOpenCR 1]
- # Check if user has skipped an attribute which can't be skipped.
- if {![string length [set text2 [htmlOpenElem $ftype $attr 0]]]} {return}
- append text $text2
- htmlGetSel
- if {$htmlIsSel || $ftype != "SCRIPT"} {
- append text "\r$htmlCurSel"
- } else {
- append text "\r<!-- Hide content from old browsers\r"
- }
- set currpos [expr [getPos] + [string length $text]]
- append text "\r"
- if {!$htmlIsSel && $ftype == "SCRIPT"} {append text "// end hiding content from old browsers -->\r"}
- append text [htmlCloseElem $ftype]
- append text "\r\r"
- if {!$htmlIsSel && $HTMLmodeVars(useTabMarks)} {append text "•"}
- if {$htmlIsSel} { deleteSelection }
- insertText $text
- if {!$htmlIsSel} {
- goto $currpos
- }
- }
-
- # Determines which list the current position is inside.
- proc htmlFindList {} {
- set listType ""
- foreach l [list UL OL DIR MENU] {
- set ex "<${l}(\[ \\t\\r\]+\[^>\]*>|>)"
- set listOpening [search -s -f 0 -i 1 -r 1 -m 0 -n $ex [getPos]]
- set ex2 </$l>
- set listClosing [search -s -f 0 -i 1 -r 1 -m 0 -n $ex2 [getPos]]
- # Search until a single list opening is found.
- while {[string length $listOpening] && [string length $listClosing] &&
- [lindex $listClosing 0] > [lindex $listOpening 0]} {
- set listOpening [search -s -f 0 -i 1 -r 1 -m 0 -n $ex [expr [lindex $listOpening 0] - 1]]
- set listClosing [search -s -f 0 -i 1 -r 1 -m 0 -n $ex2 [expr [lindex $listClosing 0] - 1]]
- }
- if {[string length $listOpening]} {
- lappend listType "$listOpening $l"
- }
- }
- set ltype [lindex [lindex $listType 0] 2]
- set lnum [lindex [lindex $listType 0] 0]
- for {set i 1} {$i < [llength $listType]} {incr i} {
- if {[lindex [lindex $listType $i] 0] > $lnum} {
- set ltype [lindex [lindex $listType $i] 2]
- set lnum [lindex [lindex $listType $i] 0]
- }
- }
- return $ltype
- }
-